package com.fly.test.restful.json;

import java.io.IOException;

import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MappingJsonFactory;

/**
 * 每个json数组中包含的json对象太多，导致用流和按行读取时加载到内存会导致内存溢出。<br>
 * <br>
 * https://blog.csdn.net/qq_40280582/article/details/121886428
 */
public class ParseByJsonToken
{
    
    /**
     * 代码中使用流和树模型解析的组合读取此文件。 <BR>
     * 每个单独的记录都以树形结构读取，但文件永远不会完整地读入内存，因此JVM内存不会爆炸。
     * 
     * @throws IOException
     */
    @Test
    public void test()
        throws IOException
    {
        JsonFactory f = new MappingJsonFactory();
        JsonParser jp = f.createParser(new ClassPathResource("data.json").getURL());
        JsonToken current;
        current = jp.nextToken();
        if (current != JsonToken.START_OBJECT)
        {
            System.out.println("Error: root should be object: quiting.");
            return;
        }
        while (jp.nextToken() != JsonToken.END_OBJECT)
        {
            String fieldName = jp.getCurrentName();
            // move from field name to field value
            current = jp.nextToken();
            if ("list".equals(fieldName))
            {
                if (current == JsonToken.START_ARRAY)
                {
                    // For each of the records in the array
                    while (jp.nextToken() != JsonToken.END_ARRAY)
                    {
                        // read the record into a tree model,
                        // this moves the parsing position to the end of it
                        JsonNode node = jp.readValueAsTree();
                        // And now we have random access to everything in the object
                        System.out.println("field1: " + node.get("title").asText());
                        System.out.println("field2: " + node.get("url").asText());
                    }
                }
                else
                {
                    System.err.println("Error: records should be an array: skipping.");
                    jp.skipChildren();
                }
            }
            else
            {
                System.out.println("Unprocessed property: " + fieldName);
                jp.skipChildren();
            }
        }
    }
}
